vue

您所在的位置:网站首页 vue router 404 vue

vue

2023-03-12 22:34| 来源: 网络整理| 查看: 265

前端路由的定义

在spa流行之前,前端路由是没有的;而像java之类的后台语言很早就有了,后端路由一般就是定义一系列的访问地址规则,路由引擎根据这些规则匹配并找到对应的处理页面,然后将请求转发给页面进行处理。 在spa应用中,前端路由是直接找到与地址匹配的一个组件或对象并将其渲染出来。改变浏览器地址而不向服务器发出请求有两种做法,一是在地址中加入#以欺骗浏览器,地址的改变是由于正在进行页内导航;二是使用HTML5的window.history功能,使用URL的Hash来模拟一个完整的URL。将单页程序分割为各自功能合理的组件或者页面,路由起到了一个非常重要的作用。它就是连接单页程序中各页面之间的链条。

路由与导航

单页式应用是没有“页”的概念的,更准确地说,Vue.js是没有页面这个概念地,Vue.js地容器就只有组件。但我们用vue-router配合组件又会形成各种的“页面”,那么我们可以这样来约定和理解: 1.页面是一个抽象的逻辑概念,用于划分功能场景 2.组件是页面在Vue的具体实现方式

router-view

渲染路径匹配到的视图组件,它还可以内嵌自己的router-view 这里我主要记录下在实际项目中,如何使用命名路由和嵌套命名视图实现布局。下图是我们需要实现的效果(这个效果标记A)index.vue:

很简单吧,我相信每个人都可以设计出这样布局的路由配置;不过,我这里有2个需求: 1.我希望main + aside这整块区域可以跳转路由;什么意思呢,就是从A可以跳转到B(也就是下面这张图)container.vue:

2.我希望main和aside两块是独立的;也就是说,main里可以跳转到其他路由,aside也可以跳转到其他路由;(当然也可以只跳转一个区域的路由,另一个路由不变)也就是从A直接跳转到C(看下图)article-detail.vue:

我们都知道,用vue-cli做项目,都会有一个顶层路由入口router-view写在app.js里面;很显然我们这里的header,main,aside,footer都在这个顶层入口里;我们先来实现一下需求1,需求1很简单,就是在顶层入口里加一个子路由;但是考虑到需求二的原因,index.vue里面需要提前加入两个命名视图来渲染首页,以便于需求二独立渲染main和aside这两个部分: router.js

import Vue from 'vue' import Router from 'vue-router' Vue.use(Router) let router = new Router({ path: '/', name: 'index', component: () => import ('@/views/index.vue') children: [ { path: '', components: { main: () => import('@/views/main.vue'), aside: () => import('@/views/aside.vue') } }, { path: 'container', component: () => import ('@/views/container.vue') } ] })

index.vue

实现需求二就和根路由设置一样了,在路由里使用两个组件来渲染即可:

import Vue from 'vue' import Router from 'vue-router' Vue.use(Router) let router = new Router({ path: '/', name: 'index', component: () => import ('@/views/index.vue'), children: [ { path: '', components: { main: () => import('@/views/main.vue'), aside: () => import('@/views/aside.vue') } }, { path: 'container', component: () => import ('@/views/container.vue') }, { path: 'article-detail', components: { main: () => import('@/views/article-detail.vue'), aside: () => import('@/views/aside.vue') } } ] })

除了上面这种做法,我再贴一个实现相同功能的代码块:

路由配置:

let router = new Router({ mode: 'history', scrollBehavior: () => ({y: 0}), routes: [ { path: '/', name: 'home', redirect: '/home', component: () => import('@/views/home.vue'), children: [ { path: 'home', component: () => import('@/views/mainAndAside.vue'), children: [ { // 这里的path为空,当父组件匹配不到路由时,默认就会渲染这个子路由 path: '', meta: { title: '首页' }, components: { main: () => import('@/views/main.vue'), aside: () => import('@/views/aside.vue') } } ] }, { path: 'container', component: () => import('@/views/container.vue'), }, { path: 'article/detail/:id', component: () => import('@/views/mainAndAside.vue'), props: true, children: [{ path: '', meta: { title: '详情页' }, components: { main: () => import('@/views/articleMain.vue'), aside: () => import('@/views/articleAside.vue') }, props: { main: true, aside: false } }] }, ]

再看一看两个核心组件的代码:

home.vue

.......

mainAndAside.vue(这里用了element-ui)

其他无关紧要的组件,就不展示了。上面这种做法,更加灵活的控制了布局,而不是将三个router-view并列排在一起,而是以一个未命名的router-view作为总入口,然后在这个组件里再设置两个命名视图;这样就可以只渲染总入口的router-view,也可以同时渲染总入口的router-view和子组件的两个命名视图;完全看路由的配置了,很灵活。

全局路由钩子之beforeEach和afterEach

简单看一下,实际应用中的代码:

let loadingInstance = null // 路由全局前置守卫 router.beforeEach((to, from, next) => { loadingInstance = Loading.service({lock: true}) let token = getCookie('token') // 修改网页标题 window.document.title = to.meta.title // token存在的情况(代表用户登录成功过) if (token) { if (!String(store.getters.token)) { store.commit('setToken', token) } if (String(store.getters.nickname) === '') { // 当vuex中没有用户数据时,从后台获取 store.dispatch('getInfo') } forbidRedirect(to, next) } else { // 如果token不存在;判断路由是否需要登录权限 if (to.meta.requireAuth) { next({ path: '/login', query: { redirect: to.fullPath } }) } else { next() } } }) // 路由全局后置守卫 router.afterEach((to, from) => { loadingInstance.close() })

在beforeEach中根据token判断用户是否登录,如果登录了,则查看vuex中有木有用户信息,没有则在vuex中执行getInfo的action获取用户信息;如果未登录,则判断将要跳转的目标路由,是否需要登录才能跳转;如果是,则使用next()导航到登录页,否则,正常跳转;另外,在beforeEach里,加载一个loading动画,在afterEach中关闭这个loading动画。

history模式

当我们把路由配置成history模式后,假如用户点击/index上的http://localhost/index)。如果我们直接在浏览器输入http://localhost/index,你会惊奇的发现浏览器会出现404的错误! 这是由于直接在浏览器中输入http://localhost/home,浏览器就会直接将这个地址请求发送至服务器,先由服务器处理路由,而客户端路由的启动条件是要访问/index.html,这样的话客户端路由就完全失效了! 解决的办法是将所有发送到服务器的请求利用服务端的URLRewrite模板重新转发给/index.html,启动VueRouter进行处理,而浏览器地址栏的URL保持不变。 这个问题在开发环境下是不会出现的,因为我们在开发环境中使用的是webpack的DevServer,DevServer是对这个问题进行了处理的,只要打开vue-cli(2.X版本)生成的项目中buid目录下的webpack.dev.config.js找到devServer配置属性就可以见到:

devServer: { historyApiFallback: { rewrites: [ { from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') }, ] } }

而当我们部署到生产环境时,就需要在web服务器上进行一些简单配置以支持Fallback。 我只用到过nginx服务器,就以这个为例吧:

location / { try_files $uri $uri/ /index.html; }

一旦我们进行了上述配置,你的服务器就不会再返回404错误页面,因为对于所有路径都会返回index.html文件。为了避免发生这种情况,应该在Vue应用里面覆盖所有的路由情况,然后再给出一个404页面。

const router = new VueRouter({ mode: 'history', routes: [ ....., ....., ....., // 这个路由应该放在最后面,否则会覆盖其他已有的路由 { path: '*', component: 404.vue} ] })


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3